﻿'/* Copyright (c) 2009, Graeme Grant (graeme@live.com.au)
' * All rights reserved.
' *
' * Redistribution and use in source and binary forms, with or without
' * modification, are permitted provided that the following conditions are met:
' *
' *   * Redistributions of source code must retain the above copyright
' *     notice, this list of conditions and the following disclaimer.
' * 
' *   * Redistributions in binary form must reproduce the above copyright
' *     notice, this list of conditions and the following disclaimer in the
' *     documentation and/or other materials provided with the distribution.
' * 
' *   * The name Graeme Grant may not be used to endorse or promote products
' *     derived from this software without specific prior written permission.
' *
' * THIS SOFTWARE IS PROVIDED BY GRAEME GRANT ``AS IS'' AND ANY
' * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
' * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
' * DISCLAIMED. IN NO EVENT SHALL Dr. WPF BE LIABLE FOR ANY
' * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
' * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
' * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
' * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
' * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
' * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
' */

Imports System.Net
Imports System.IO
Imports System.Web

Public Class EtsyNET

#Region " Public Properties"

    Private _apiKey As String
    Public Property ApiKey() As String
        Get
            Return _apiKey
        End Get
        Set(ByVal value As String)
            _apiKey = value
        End Set
    End Property

    Public ReadOnly Property BaseURL() As String
        Get
            Return "http://beta-api.etsy.com/v1"
        End Get
    End Property

#End Region

#Region "Constructor"

    Public Sub New()

    End Sub

    Public Sub New(ByVal ApiKey As String)
        Me.ApiKey = ApiKey
    End Sub

#End Region

#Region "Commands"

#Region "User Commands"

    Public Function getUserDetails(ByVal UserID As Long, _
                                   Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low) _
                                   As User
        Return getUserDetails(UserID.ToString, DetailLevel)
    End Function

    Public Function getUserDetails(ByVal UserName As String, _
                                   Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low) _
                                   As User
        Dim parameters As New Hashtable
        parameters.Add("uri", "/users/")
        parameters.Add("request", UserName)
        parameters.Add("api_key", _apiKey)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.User
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getUsersByName(ByVal SearchName As String, _
                                   Optional ByVal Limit As Integer = 10, _
                                   Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                   Optional ByVal Offset As Integer = 0) _
                                   As Users(Of User)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/users/keywords/")
        parameters.Add("api_key", _apiKey)
        parameters.Add("request", SearchName)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Users
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

#End Region

#Region "Shop Commands"

    Public Function getShopDetails(ByVal UserID As Long, _
                                   Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low) _
                                   As Shop
        Return getShopDetails(UserID.ToString, DetailLevel)
    End Function

    Public Function getShopDetails(ByVal UserName As String, _
                                   Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low) _
                                   As Shop

        Dim parameters As New Hashtable
        parameters.Add("uri", "/shops/")
        parameters.Add("request", UserName)
        parameters.Add("api_key", _apiKey)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Shop
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getShopListings(ByVal UserID As Long, _
                                    Optional ByVal SortOn As Enums.sort_on = Enums.sort_on.created, _
                                    Optional ByVal SortOrder As Enums.sort_order = Enums.sort_order.down, _
                                    Optional ByVal SectionID As Integer = Nothing, _
                                    Optional ByVal Limit As Integer = 10, _
                                    Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                    Optional ByVal Offset As Integer = 0) _
                                    As Listings(Of Listing)

        Return getShopListings(UserID.ToString, SortOn, SortOrder, SectionID, Limit, DetailLevel, Offset)

    End Function

    Public Function getShopListings(ByVal UserName As String, _
                                    Optional ByVal SortOn As Enums.sort_on = Enums.sort_on.created, _
                                    Optional ByVal SortOrder As Enums.sort_order = Enums.sort_order.down, _
                                    Optional ByVal SectionID As Integer = Nothing, _
                                    Optional ByVal Limit As Integer = 10, _
                                    Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                    Optional ByVal Offset As Integer = 0) _
                                    As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/shops/{0}/", UserName))
        parameters.Add("request", "listings")
        parameters.Add("sort_on", SortOn)
        parameters.Add("sort_order", SortOrder)
        If Not SectionID = Nothing Then parameters.Add("section_id", SectionID)
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getFeaturedDetails(ByVal UserID As Long, _
                                   Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low) _
                                   As Listings(Of Listing)
        Return getFeaturedDetails(UserID.ToString, DetailLevel)
    End Function

    Public Function getFeaturedDetails(ByVal UserName As String, _
                                   Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low) _
                                   As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/shops/{0}/listings/", UserName))
        parameters.Add("request", "featured")
        parameters.Add("api_key", _apiKey)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getFeaturedSellers(Optional ByVal Limit As Integer = 10, _
                                      Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                      Optional ByVal Offset As Integer = 0) _
                                      As Shops(Of Shop)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/shops/")
        parameters.Add("request", "featured")
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Shops
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getShopsByName(ByVal SearchName As String, _
                                   Optional ByVal Limit As Integer = 10, _
                                   Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                   Optional ByVal SortOrder As Enums.sort_order = Enums.sort_order.down, _
                                   Optional ByVal Offset As Integer = 0) _
                                   As Shops(Of Shop)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/shops/keywords/")
        parameters.Add("request", SearchName)
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("sort_order", SortOrder.ToString)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Shops
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

#End Region

#Region "Listing Commands"

    Public Function getListingDetails(ByVal ListingID As Long, _
                                      Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low) _
                                      As Listing
        Dim parameters As New Hashtable
        parameters.Add("uri", "/listings/")
        parameters.Add("request", ListingID)
        parameters.Add("api_key", _apiKey)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listing
            Case Else
                Throw New EtsyException(result.Status)
        End Select
        ''
    End Function

    Public Function getAllListings(Optional ByVal Limit As Integer = 10, _
                                   Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                   Optional ByVal SortOn As Enums.sort_on_range = Enums.sort_on.created, _
                                   Optional ByVal SortOrder As Enums.sort_order = Enums.sort_order.down, _
                                   Optional ByVal Offset As Integer = 0) _
                                   As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/listings/")
        parameters.Add("request", "all")
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("sort_on", SortOn)
        parameters.Add("sort_order", SortOrder)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getListingsByCategory(ByVal Category As String, _
                                          Optional ByVal Limit As Integer = 10, _
                                          Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                          Optional ByVal SortOn As Enums.sort_on = Enums.sort_on.created, _
                                          Optional ByVal SortOrder As Enums.sort_order = Enums.sort_order.down, _
                                          Optional ByVal Offset As Integer = 0) _
                                          As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/listings/category/")
        parameters.Add("request", Category)
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("sort_on", SortOn)
        parameters.Add("sort_order", SortOrder)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getListingsByColor(ByVal Color_Triplet As ColorRGB, _
                                          Optional ByVal Wiggle As Integer = 5, _
                                          Optional ByVal Limit As Integer = 10, _
                                          Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                          Optional ByVal Offset As Integer = 0) _
                                          As Listings(Of Listing)

        Return _getListingsByColor(Color_Triplet.ToString, Wiggle, Limit, DetailLevel, Offset)

    End Function

    Public Function getListingsByColor(ByVal Color_Triplet As ColorHSV, _
                                      Optional ByVal Wiggle As Integer = 5, _
                                      Optional ByVal Limit As Integer = 10, _
                                      Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                      Optional ByVal Offset As Integer = 0) _
                                      As Listings(Of Listing)

        Return _getListingsByColor(Color_Triplet.ToString, Wiggle, Limit, DetailLevel, Offset)

    End Function

    Private Function _getListingsByColor(ByVal Color_Triplet As String, _
                                         Optional ByVal Wiggle As Integer = 5, _
                                         Optional ByVal Limit As Integer = 10, _
                                         Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                         Optional ByVal Offset As Integer = 0) _
                                         As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/listings/color/")
        parameters.Add("request", Color_Triplet)
        parameters.Add("api_key", _apiKey)
        parameters.Add("wiggle", Wiggle)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getListingsByColorAndKeywords(ByVal Search_Terms As String, _
                                                  ByVal Color_Triplet As ColorRGB, _
                                                  Optional ByVal Wiggle As Integer = 5, _
                                                  Optional ByVal Limit As Integer = 10, _
                                                  Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                                  Optional ByVal Offset As Integer = 0) _
                                                  As Listings(Of Listing)

        Return _getListingsByColorAndKeywords(Search_Terms, Color_Triplet.ToString, Wiggle, Limit, DetailLevel, Offset)

    End Function

    Public Function getListingsByColorAndKeywords(ByVal Search_Terms As String, _
                                                  ByVal Color_Triplet As ColorHSV, _
                                                  Optional ByVal Wiggle As Integer = 5, _
                                                  Optional ByVal Limit As Integer = 10, _
                                                  Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                                  Optional ByVal Offset As Integer = 0) _
                                                  As Listings(Of Listing)

        Return _getListingsByColorAndKeywords(Search_Terms, Color_Triplet.ToString, Wiggle, Limit, DetailLevel, Offset)

    End Function

    Private Function _getListingsByColorAndKeywords(ByVal Search_Terms As String, _
                                                    ByVal Color_Triplet As String, _
                                                    Optional ByVal Wiggle As Integer = 5, _
                                                    Optional ByVal Limit As Integer = 10, _
                                                    Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                                    Optional ByVal Offset As Integer = 0) _
                                                    As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/listings/color/{0}/keywords/", Color_Triplet))
        parameters.Add("request", Search_Terms)
        parameters.Add("api_key", _apiKey)
        parameters.Add("wiggle", Wiggle)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getFrontFeaturedListings(Optional ByVal Limit As Integer = 10, _
                                             Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                             Optional ByVal Offset As Integer = 0) _
                                             As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/listings/featured/")
        parameters.Add("request", "front")
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getListingsByKeyword(ByVal SearchTerms As String, _
                                      ByVal MinPrice As Decimal, _
                                      ByVal MaxPrice As Decimal, _
                                      Optional ByVal Limit As Integer = 10, _
                                      Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                      Optional ByVal SortOn As Enums.sort_on = Enums.sort_on.created, _
                                      Optional ByVal SortOrder As Enums.sort_order = Enums.sort_order.down, _
                                      Optional ByVal SearchDescription As Boolean = False, _
                                      Optional ByVal Offset As Integer = 0) _
                                      As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/listings/keywords/")
        parameters.Add("request", SearchTerms)
        parameters.Add("api_key", _apiKey)
        parameters.Add("min_price", MinPrice)
        parameters.Add("max_price", MaxPrice)
        parameters.Add("search_description", SearchDescription.ToString.ToLower)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("sort_on", SortOn)
        parameters.Add("sort_order", SortOrder)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getListingsByMaterials(ByVal Materials As String, _
                                      Optional ByVal Limit As Integer = 10, _
                                      Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                      Optional ByVal SortOn As Enums.sort_on = Enums.sort_on.created, _
                                      Optional ByVal SortOrder As Enums.sort_order = Enums.sort_order.down, _
                                      Optional ByVal Offset As Integer = 0) _
                                      As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/listings/materials/")
        parameters.Add("request", Materials)
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("sort_on", SortOn.ToString)
        parameters.Add("sort_order", SortOrder.ToString)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getListingsByTags(ByVal Tags As String, _
                                      Optional ByVal Limit As Integer = 10, _
                                      Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                      Optional ByVal SortOn As Enums.sort_on = Enums.sort_on.created, _
                                      Optional ByVal SortOrder As Enums.sort_order = Enums.sort_order.down, _
                                      Optional ByVal Offset As Integer = 0) _
                                      As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/listings/tags/")
        parameters.Add("request", Tags)
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("sort_on", SortOn.ToString)
        parameters.Add("sort_order", SortOrder.ToString)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

#End Region

#Region "Feeback Commands"

    Public Function getFeedbackForUser(ByVal UserID As Long, _
                                       Optional ByVal Limit As Integer = 10, _
                                       Optional ByVal Offset As Integer = 0) _
                                       As FeedBacks(Of Feedback)
        Return getFeedbackForUser(UserID.ToString, Limit, Offset)
    End Function

    Public Function getFeedbackForUser(ByVal UserName As String, _
                                           Optional ByVal Limit As Integer = 10, _
                                           Optional ByVal Offset As Integer = 0) _
                                           As FeedBacks(Of Feedback)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/users/{0}/", UserName))
        parameters.Add("request", "feedback")
        parameters.Add("api_key", _apiKey)
        parameters.Add("limit", Limit)
        parameters.Add("offset", Offset)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.FeedBacks
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getFeedbackAsBuyer(ByVal UserID As Long, _
                                       Optional ByVal Limit As Integer = 10, _
                                       Optional ByVal Offset As Integer = 0) _
                                       As FeedBacks(Of Feedback)
        Return getFeedbackAsBuyer(UserID.ToString, Limit, Offset)
    End Function

    Public Function getFeedbackAsBuyer(ByVal UserName As String, _
                                           Optional ByVal Limit As Integer = 10, _
                                           Optional ByVal Offset As Integer = 0) _
                                           As FeedBacks(Of Feedback)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/users/{0}/feedback/", UserName))
        parameters.Add("request", "buyer")
        parameters.Add("api_key", _apiKey)
        parameters.Add("limit", Limit)
        parameters.Add("offset", Offset)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.FeedBacks
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getFeedbackForOthers(ByVal UserID As Long, _
                                         Optional ByVal Limit As Integer = 10, _
                                         Optional ByVal Offset As Integer = 0) _
                                         As FeedBacks(Of Feedback)
        Return getFeedbackForOthers(UserID.ToString, Limit, Offset)
    End Function

    Public Function getFeedbackForOthers(ByVal UserName As String, _
                                         Optional ByVal Limit As Integer = 10, _
                                         Optional ByVal Offset As Integer = 0) _
                                         As FeedBacks(Of Feedback)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/users/{0}/feedback/", UserName))
        parameters.Add("request", "others")
        parameters.Add("api_key", _apiKey)
        parameters.Add("limit", Limit)
        parameters.Add("offset", Offset)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.FeedBacks
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getFeedbackAsSeller(ByVal UserID As Long, _
                                        Optional ByVal Limit As Integer = 10, _
                                        Optional ByVal Offset As Integer = 0) _
                                        As FeedBacks(Of Feedback)
        Return getFeedbackAsSeller(UserID.ToString, Limit, Offset)
    End Function

    Public Function getFeedbackAsSeller(ByVal UserName As String, _
                                        Optional ByVal Limit As Integer = 10, _
                                        Optional ByVal Offset As Integer = 0) _
                                        As FeedBacks(Of Feedback)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/users/{0}/feedback/", UserName))
        parameters.Add("request", "seller")
        parameters.Add("api_key", _apiKey)
        parameters.Add("limit", Limit)
        parameters.Add("offset", Offset)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.FeedBacks
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

#End Region

#Region "Tag Commands"

    Public Function getTopCategories() As ArrayList

        Dim parameters As New Hashtable
        parameters.Add("uri", "/categories")
        'parameters.Add("request", "top")
        parameters.Add("api_key", _apiKey)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Tags
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getChildCategories(ByVal Category As String) As ArrayList

        Dim parameters As New Hashtable
        'parameters.Add("uri", "/categories/children/")
        parameters.Add("uri", String.Format("/categories/{0}/", Category))
        parameters.Add("request", "children")
        parameters.Add("api_key", _apiKey)
        'parameters.Add("category", Category)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Tags
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getTopTags() As ArrayList

        Dim parameters As New Hashtable
        parameters.Add("uri", "/tags")
        'parameters.Add("request", "top")
        parameters.Add("api_key", _apiKey)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Tags
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getChildTags(ByVal Tag As String) As ArrayList

        Dim parameters As New Hashtable
        'parameters.Add("uri", "/tags/children/")
        parameters.Add("uri", String.Format("/tags/{0}/", Tag))
        parameters.Add("request", "children")
        parameters.Add("api_key", _apiKey)
        'parameters.Add("tag", Tag)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Tags
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

#End Region

#Region "Favourites Commands"

    Public Function getFavorersOfListing(ByVal ListingID As Long, _
                                         Optional ByVal Limit As Integer = 10, _
                                         Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                         Optional ByVal Offset As Integer = 0) _
                                         As Users(Of User)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/listings/{0}/", ListingID))
        parameters.Add("request", "favorers")
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Users
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getFavorersOfShop(ByVal UserID As Long, _
                                      Optional ByVal Limit As Integer = 10, _
                                      Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                      Optional ByVal Offset As Integer = 0) _
                                      As Users(Of User)
        Return getFavorersOfShop(UserID.ToString, Limit, DetailLevel, Offset)
    End Function

    Public Function getFavorersOfShop(ByVal UserName As String, _
                                      Optional ByVal Limit As Integer = 10, _
                                      Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                      Optional ByVal Offset As Integer = 0) _
                                      As Users(Of User)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/shops/{0}/", UserName))
        parameters.Add("request", "favorers")
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Users
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getFavoriteListingsOfUser(ByVal UserID As Long, _
                                          Optional ByVal Limit As Integer = 10, _
                                          Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                          Optional ByVal Offset As Integer = 0) _
                                          As Listings(Of Listing)
        Return getFavoriteListingsOfUser(UserID.ToString, Limit, DetailLevel, Offset)
    End Function

    Public Function getFavoriteListingsOfUser(ByVal UserName As String, _
                                              Optional ByVal Limit As Integer = 10, _
                                              Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                              Optional ByVal Offset As Integer = 0) _
                                              As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/users/{0}/favorites/", UserName))
        parameters.Add("request", "listings")
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getFavoriteShopsOfUser(ByVal UserID As Long, _
                                               Optional ByVal Limit As Integer = 10, _
                                               Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                               Optional ByVal Offset As Integer = 0) _
                                               As Shops(Of Shop)
        Return getFavoriteShopsOfUser(UserID.ToString, Limit, DetailLevel, Offset)
    End Function

    Public Function getFavoriteShopsOfUser(ByVal UserName As String, _
                                           Optional ByVal Limit As Integer = 10, _
                                           Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                           Optional ByVal Offset As Integer = 0) _
                                           As Shops(Of Shop)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/users/{0}/favorites/", UserName))
        parameters.Add("request", "shops")
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Shops
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

#End Region

#Region "Gift Guide Commands"

    Public Function getGiftGuides() As GiftGuides(Of GiftGuide)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/")
        parameters.Add("request", "gift-guides")
        parameters.Add("api_key", _apiKey)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.GiftGuides
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function getGiftGuideListings(ByVal GuideID As Long, _
                                    Optional ByVal Limit As Integer = 10, _
                                    Optional ByVal DetailLevel As Enums.detail_level = Enums.detail_level.low, _
                                    Optional ByVal Offset As Integer = 0) _
                                    As Listings(Of Listing)

        Dim parameters As New Hashtable
        parameters.Add("uri", String.Format("/gift-guides/{0}/", GuideID))
        parameters.Add("request", "listings")
        parameters.Add("api_key", _apiKey)
        parameters.Add("offset", Offset)
        parameters.Add("limit", Limit)
        parameters.Add("detail_level", DetailLevel.ToString)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Listings
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

#End Region

#Region "Server Commands"

    Public Function getMethodTable() As Methods(Of Method)

        Dim parameters As New Hashtable
        parameters.Add("uri", "/")
        parameters.Add("request", "")
        parameters.Add("api_key", _apiKey)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Methods
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    'Public Function getFeedback(ByVal feedback_id As Long) _
    '                            As User

    '    Dim parameters As New Hashtable
    '    parameters.Add("uri", "/feedback/")
    '    parameters.Add("request", feedback_id)
    '    parameters.Add("api_key", _apiKey)

    '    Dim result As Response = GetResponse(parameters)
    '    Select Case result.Status
    '        Case Enums.response_codes.OK
    '            Return result.User
    '        Case Else
    '            Throw New EtsyException(result.Status)
    '    End Select

    'End Function

    Public Function getServerEpoch() As DateTime

        Dim parameters As New Hashtable
        parameters.Add("uri", "/server/")
        parameters.Add("request", "epoch")
        parameters.Add("api_key", _apiKey)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.ServerEpoch
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

    Public Function Ping() As String

        Dim parameters As New Hashtable
        parameters.Add("uri", "/server/")
        parameters.Add("request", "ping")
        parameters.Add("api_key", _apiKey)

        Dim result As Response = GetResponse(parameters)
        Select Case result.Status
            Case Enums.response_codes.OK
                Return result.Ping
            Case Else
                Throw New EtsyException(result.Status)
        End Select

    End Function

#End Region

#End Region

#Region "Support Methods & Functions"

#Region "Get"

    Private Function GetResponse(ByVal paramaters As Hashtable) As Response

        CheckApiKey()

        Dim url As String = BaseURL
        url += String.Format("{0}{1}?", paramaters("uri"), paramaters("request"))
        Dim variables As String = ""
        paramaters.Remove("uri")
        paramaters.Remove("request")

        For Each key As String In paramaters.Keys
            variables += String.Format("&{0}={1}", key, paramaters(key))
        Next
        url += variables.Substring(1)

        Return DoGetResponse(url)

    End Function

    Private Function DoGetResponse(ByVal url As String) As Response

        Dim objResponse As WebResponse
        Dim result As New Response
        result.Status = Enums.response_codes.OK

        Console.WriteLine("API URL: {0}", url)
        Console.WriteLine("Calling Etsy...")

        Try

            Dim objRequest As WebRequest = HttpWebRequest.Create(url)
            objResponse = objRequest.GetResponse()

            Dim objStreamReader As New StreamReader(objResponse.GetResponseStream())
            result.Data = objStreamReader.ReadToEnd

            objStreamReader.Close()
            objResponse.Close()

        Catch ex As WebException
            result.Status = CType(ex.Response, HttpWebResponse).StatusCode

        Catch ex As Exception

            Throw (ex)

        End Try

        If result.Data IsNot Nothing Then Console.WriteLine("{0:#,##0} bytes received...", result.Data.Length)
        Return result

    End Function

#End Region

#Region "Validation"

    Private Sub CheckApiKey()
        If ApiKey = Nothing OrElse ApiKey.Length = 0 Then
            Throw New ApiKeyRequiredException()
        End If
    End Sub

#End Region

#End Region

End Class
